Skip to content

fix(i18n): require an explicit locale on presentation helpers - #4640

Merged
Astro-Han merged 1 commit into
apache:mainfrom
orangeCatDeveloper:fix/locale-silent-defaults
Sep 5, 2026
Merged

fix(i18n): require an explicit locale on presentation helpers#4640
Astro-Han merged 1 commit into
apache:mainfrom
orangeCatDeveloper:fix/locale-silent-defaults

Conversation

@orangeCatDeveloper

@orangeCatDeveloper orangeCatDeveloper commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Presentation helpers across desktop renderer, @maka/core, and @maka/ui defaulted their locale parameter, so a caller that forgot to pass it rendered the wrong language with no type error: 'zh' defaults showed Chinese to English users, and the "en" defaults on materializeChat / materializeTurns / contextCompactionNotice did the reverse. This PR removes every such default (27 helpers) so the locale is a required argument, and makes TranscriptProjectionInput.locale required for the same reason. No production caller relied on a default — every one already passed the locale it had in scope — so the runtime behavior is unchanged; only the type-level guarantee is new. Tests that leaned on a default now pass the locale explicitly.

Where a required locale now follows an optional parameter (now in the three relative-time helpers, depth in formatAsKeyValueLines), that leading default is dropped too: it became unreachable and every caller already passed it.

The guard for this change is tsc, not the tests: restoring a default keeps the existing assertions green. The 'en' assertions added to the touched test files prove the English path for those helpers only; they are not a per-helper sweep.

The six @maka/ui streaming helpers with the same defect are fixed in #4524 and are not touched here; the two OAuth result helpers are fixed in #4551. A lint rule that rejects any future UiLocale default is left for a follow-up.

Refs #2672

Verification

workspace typecheck:                    0 errors
packages/core tests (dist):             779 pass / 0 fail
packages/ui tests (dist):               347 pass / 0 fail
desktop main tests (dist):              2029 pass / 0 fail
renderer architecture check:            passed against origin/main
biome (changed files):                  clean
git grep "UiLocale = ['\"](zh|en)['\"]|locale ?? ['\"](zh|en)['\"]" (non-test):
  only the #4524 / #4551 sites and the CLI's optional-input fallback remain

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code — implementation, tests, and this description, under the contributor's direction; the commit carries a Generated-by: Claude Code trailer.

Checklist

  • Tests cover the change and fail without it (the guard is tsc; see Summary)

@github-actions github-actions Bot added the effort/M Under 500 readable lines label Sep 3, 2026
@orangeCatDeveloper
orangeCatDeveloper marked this pull request as ready for review September 3, 2026 09:30

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call-site claim holds up: ci.yml runs npm run typecheck across the workspaces whenever code changes, packages/ui/stories is covered through apps/desktop/tsconfig.storybook.json, and nothing outside the typechecked configs calls these helpers (no .mjs, .js or e2e caller), so a green CI does prove every caller was updated. Both packages are private, so removing the defaults breaks no published surface. Two things to settle first.

P2: the sweep only covered 'zh', so the title's claim does not hold. The verification grep was "locale: UiLocale = 'zh'|locale ?? 'zh'", which misses the same defect spelled with double quotes and the other locale. Still on head: packages/ui/src/materialize.ts:153 (materializeChat(messages, locale: UiLocale = "en")), packages/ui/src/materialize.ts:667 (materializeTurns), and apps/desktop/src/renderer/app-shell-context-compaction.ts:35 (contextCompactionNotice(outcome, uiLocale: UiLocale = 'en')). The two materialize helpers are the main transcript presentation path, and they are not in #4524's file list (that PR touches materialize.test.ts but not materialize.ts) or #4551's, so no follow-up currently claims them. A caller that forgets renders English to Chinese users: the direction is flipped, the defect is the same. Either fold them in or name them in the body as deliberately out of scope, otherwise this reads as complete and the #2672 item gets closed while three helpers still default.

P3: nothing stops the next one. This PR and #4524 and #4551 all rely on a one-off grep; there is no lint rule or check-renderer-architecture entry asserting that a UiLocale parameter carries no default. Adding one is what actually closes this class out. Not blocking.

P3: two claims in the description do not hold, and I would rather they were stated accurately than dropped. "Tests cover the change and fail without it" is not the case: restore the defaults and all four touched test files still pass, because passing 'zh' explicitly gives the same result and the new 'en' assertions pass either way. The guard for this change is tsc, which is a fine answer, just a different one. And "each touched helper gained one 'en' assertion" is 4 assertions against 24 helpers; even among the tested ones, describeTurnErrorClass (session-error-presentation.test.ts:31) still only has a 'zh' assertion.

No conflict or ordering dependency with #4641: git merge-tree on the two heads is clean, and the only shared file is provider-panel-shared.ts, where #4640 changes signatures and #4641 deletes a branch inside one body. Worth knowing that #4551 also edits that file plus settings-provider-copy.ts, so whichever of the three lands last rebases once.

Comment thread packages/core/src/relative-time.ts Outdated
Comment thread packages/core/src/tool-quiet-preview.ts
@orangeCatDeveloper
orangeCatDeveloper force-pushed the fix/locale-silent-defaults branch 6 times, most recently from 0877e02 to d98ab14 Compare September 4, 2026 18:02
A locale default let any caller that forgot the argument render the
wrong language without a type error: 'zh' defaults showed Chinese to
English users, 'en' defaults the reverse.

Generated-by: Claude Code
@orangeCatDeveloper
orangeCatDeveloper force-pushed the fix/locale-silent-defaults branch from d98ab14 to 7b5bdd8 Compare September 5, 2026 01:54
@orangeCatDeveloper

Copy link
Copy Markdown
Contributor Author

@Astro-Han Comments are addressed.

  • P2: the three "en" defaults (materializeChat, materializeTurns, contextCompactionNotice) are now required parameters in this PR.
  • Inline P3s: the unreachable now = Date.now() and depth = 0 defaults are dropped.
  • P3 lint rule: chore(ci): ratchet locale hygiene #4817 adds a silent-locale-default ratchet rule that fails CI on any new locale: UiLocale = '…'.
  • P3 description: reworded to say the guard is tsc, and that the 'en' assertions cover only the touched test files.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 7b5bdd8. Everything from the last round is closed: materializeChat / materializeTurns / contextCompactionNotice are required now, the unreachable now / depth defaults are gone, and the body says plainly that tsc is the guard. I re-checked the production callers that used to lean on a default (chat-view.tsx, app-shell-turn-view-model.ts, quote-companion-panel.tsx, artifact-pane.tsx, tasks-settings-page.tsx, session-history-list.tsx) and every one passes the locale it has in scope, so runtime behavior is unchanged. The ledger delta is the two = 'en' tokens, downward only.

One number: the body says 27 helpers, the diff removes 33 defaults plus makes three locale?: fields required. Worth fixing before squash since the title becomes the commit.

Ordering: #4823 edits the same app-shell-context-compaction.ts entry in renderer-architecture.json two lines away from your change, so whichever lands second should regenerate the ledger rather than resolve the conflict by hand. No dependency either way.

AI-assisted review: drafted with Maka; I verified the caller list and the ledger delta myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants